﻿Imports System.Xml.Serialization
Imports dooll.Config

''' <summary>
''' 支付方式配置对象
''' </summary>
''' <remarks></remarks>
Public Class PaymentConfig
    Inherits DefaultConfig
    ''' <summary>
    ''' 配置信息
    ''' </summary>
    ''' <remarks></remarks>
    Private Shared mConfigInfo As PaymentConfigInfo
    Private Shared mConfigFilePath As String
    Private Shared mFileDateTime As DateTime = DateTime.Now

    Public Shared ReadOnly Property ConfigInfo() As PaymentConfigInfo
        Get
            Return mConfigInfo
        End Get
    End Property

    Shared Sub New()
        mConfigInfo = load()
    End Sub

    REM 配置文件路径
    Public Overloads Shared ReadOnly Property ConfigFilePath() As String
        Get
            If String.IsNullOrEmpty(mConfigFilePath) Then
                Dim Path As String = AppSettings("ConfigPath")
                If Not Path.EndsWith("/") Then Path = String.Concat(Path, "/")
                Path = System.Web.HttpContext.Current.Server.MapPath(String.Format("{0}payment.config", Path))
                If IO.File.Exists(Path) Then
                    mConfigFilePath = Path
                Else
                    Path = Nothing
                End If
            End If
            Return mConfigFilePath
        End Get
    End Property

    Public Shared Function load() As PaymentConfigInfo
        If IO.File.Exists(ConfigFilePath) Then
            Try
                If mConfigInfo Is Nothing Then
                    mConfigInfo = New PaymentConfigInfo
                End If
                Return CType(LoadConfig(mFileDateTime, ConfigFilePath, mConfigInfo, False), PaymentConfigInfo)
            Catch ex As Exception
                mErrMessage = ex.Message
                Return New PaymentConfigInfo
            End Try
        Else
            mErrMessage = String.Format("路径{0}不存在", ConfigFilePath)
        End If
        Return New PaymentConfigInfo
    End Function

    Protected Overrides Sub Finalize()
        mConfigInfo = Nothing
        MyBase.Finalize()
    End Sub
End Class

''' <summary>
''' 支付方式配置对象
''' </summary>
''' <remarks></remarks>
<Serializable()> <XmlRoot("Payment")> Public Class PaymentConfigInfo
    Implements IConfigInfo
    Public Alipay As AlipayConfigInfo = New AlipayConfigInfo
End Class


''' <summary>
''' 支付宝配置对象
''' </summary>
''' <remarks></remarks>
<Serializable()> Public Class AlipayConfigInfo

    ''' <summary>
    ''' 是否启用
    ''' </summary>
    ''' <remarks></remarks>
    <XmlAttribute("enabled")> Public enabled As Boolean = False

    ''' <summary>
    ''' 是否打开调试日志
    ''' </summary>
    ''' <remarks></remarks>
    <XmlAttribute("debug")> Public debug As Boolean = False

    ''' <summary>
    ''' 网关地址 默认 https://www.alipay.com/cooperate/gateway.do?
    ''' </summary>
    ''' <remarks></remarks>
    Public gateway As String = "https://www.alipay.com/cooperate/gateway.do?"


    ''' <summary>
    ''' 字符编码格式 目前支持 gbk 或 utf-8
    ''' </summary>
    ''' <remarks></remarks>
    Public inputcharset As String = "utf-8"

    ''' <summary>
    ''' 合作ID
    ''' </summary>
    ''' <remarks></remarks>
    Public partner As String = ""

    ''' <summary>
    ''' 安全校验码
    ''' </summary>
    ''' <remarks></remarks>
    Public key As String = ""

    ''' <summary>
    ''' 签名结果
    ''' </summary>
    ''' <remarks></remarks>
    Public ReadOnly Property sign As String
        Get

            Dim sPara As String() = toSignParamArray()
            '获得签名结果
            Dim mysign = Alipay.Util.build_mysign(sPara, key.Trim(), sign_type.Trim().ToUpper(), inputcharset.Trim().ToLower())
            Return mysign
        End Get
    End Property

    ''' <summary>
    ''' 签名方式
    ''' </summary>
    ''' <remarks></remarks>
    Public sign_type As String = "MD5"

    ''' <summary>
    ''' 访问模式
    ''' </summary>
    ''' <remarks></remarks>
    Public transport As String = "https"

    ''' <summary>
    ''' 网站订单系统中的唯一订单号匹配
    ''' </summary>
    ''' <remarks></remarks>
    Public out_trade_no As String = ""

    ''' <summary>
    ''' 订单名称，显示在支付宝收银台里的“商品名称”里，显示在支付宝的交易管理的“商品名称”的列表里
    ''' </summary>
    ''' <remarks></remarks>
    Public subject As String = ""

    ''' <summary>
    ''' 订单描述、订单详细、订单备注，显示在支付宝收银台里的“商品描述”里
    ''' </summary>
    ''' <remarks></remarks>
    Public body As String = ""

    ''' <summary>
    ''' 订单总金额，显示在支付宝收银台里的“应付总额”里
    ''' </summary>
    ''' <remarks></remarks>
    Public total_fee As String = ""

    ''' <summary>
    ''' 默认支付方式，四个值可选：bankPay(网银); cartoon(卡通); directPay(余额); CASH(网点支付)，初始值
    ''' </summary>
    ''' <remarks></remarks>
    Public paymethod As String = ""

    ''' <summary>
    ''' 默认网银代号，代号列表见http://club.alipay.com/read.php?tid=8681379 初始值
    ''' </summary>
    ''' <remarks></remarks>
    Public defaultbank As String = ""

    ''' <summary>
    ''' 防钓鱼时间戳 alipay_function.query_timestamp(partner)
    ''' </summary>
    ''' <remarks></remarks>
    Public anti_phishing_key As String = ""

    ''' <summary>
    ''' 获取客户端的IP地址，建议：编写获取客户端IP地址的程序
    ''' </summary>
    ''' <remarks></remarks>s
    Public exter_invoke_ip As String = ""

    ''' <summary>
    ''' 自定义参数，可存放任何内容（除url的特殊字符外），不会显示在页面上
    ''' </summary>
    ''' <remarks></remarks>
    Public extra_common_param As String = ""

    ''' <summary>
    ''' 默认买家支付宝账号
    ''' </summary>
    ''' <remarks></remarks>
    Public buyer_email As String = ""

    ''' <summary>
    ''' 提成类型，该值为固定值：10，不需要修改
    ''' </summary>
    ''' <remarks></remarks>
    Public royalty_type As String = ""

    ''' <summary>
    ''' 提成信息集，与需要结合商户网站自身情况动态获取每笔交易的各分润收款账号、各分润金额、各分润说明。最多只能设置10条
    ''' 各分润金额的总和须小于等于total_fee
    ''' 提成信息集格式为：收款方Email_1^金额1^备注1|收款方Email_2^金额2^备注2
    ''' 如：
    ''' royalty_type = "10"
    ''' royalty_parameters = "111@126.com^0.01^分润备注一|222@126.com^0.01^分润备注二"
    ''' </summary>
    ''' <remarks></remarks>
    Public royalty_parameters As String = ""

    ''' <summary>
    ''' 网站商品的展示地址，不允许加?id=123这类自定义参数
    ''' </summary>
    ''' <remarks></remarks>
    Public show_url As String = ""

    ''' <summary>
    ''' 通知的路径
    ''' </summary>
    ''' <remarks></remarks>
    Public notify_url As String = ""

    ''' <summary>
    ''' 用户返回的页面
    ''' </summary>
    ''' <remarks></remarks>
    Public return_url As String = ""

    ''' <summary>
    ''' 存储过程参数数组
    ''' </summary>
    ''' <remarks></remarks>
    <XmlElement("param")> Public param() As ParamItem = {}    '其他附加配置的参数

    ''' <summary>
    ''' 转换成这符串
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function toParamArray() As String()
        Dim s As String = String.Empty
        If param.Length = 0 Then
            Return {}
        End If
        For i As Integer = 0 To param.Length - 1
            s = String.Concat(s, IIf(i = 0, "", ","), param(i).name, "=", Replace(param(i).value, ",", ""))
        Next
        Return s.Split(",")
    End Function

    Public Function toSignParamArray() As String()
        Dim rtnValue As String() = {"_input_charset=" & inputcharset, "out_trade_no=" & out_trade_no, "subject=" & subject, "body=" & body, "total_fee=" & total_fee, "paymethod=" & paymethod, "defaultbank=" & defaultbank, "show_url=" & show_url, "partner=" & partner, "return_url=" & return_url, "notify_url=" & notify_url}
        Dim oldLength As Integer = rtnValue.Length
        Dim pa As String() = toParamArray()

        ReDim Preserve rtnValue(oldLength + pa.Length - 1)
        pa.CopyTo(rtnValue, oldLength)
        rtnValue = Alipay.Util.para_filter(rtnValue)
        rtnValue = Alipay.Util.arg_sort(rtnValue)
        Return rtnValue
    End Function

    Public Function getSignFromParams(ByVal sPara As String()) As String
        sPara = Alipay.Util.para_filter(sPara)
        sPara = Alipay.Util.arg_sort(sPara)
        Dim mysign = Alipay.Util.build_mysign(sPara, key.Trim(), sign_type.Trim().ToUpper(), inputcharset.Trim().ToLower())
        Return mysign

    End Function

    '构造表单提交HTML
    '输出 表单提交HTML文本
    Public Function BuildForm(Optional ByVal mode As String = "get") As String
        Dim sHtml As Text.StringBuilder = New Text.StringBuilder()

        If mode = "get" Then
            'GET方式传递
            sHtml.Append(String.Concat("<form id='alipaysubmit' name='alipaysubmit' action='", gateway, "' method='get'>"))
        Else
            'POST方式传递（GET与POST二必选一）
            sHtml.Append(String.Concat("<form id='alipaysubmit' name='alipaysubmit' action='", gateway, "' method='post'>"))
        End If


        Dim SignParas As String() = toSignParamArray()

        Dim nCount As Integer = UBound(SignParas)
        Dim i, pos, nLen As Integer
        Dim itemName, itemValue As String
        For i = 0 To nCount
            '把sArray的数组里的元素格式：变量名=值，分割开来
            pos = InStr(SignParas(i), "=")                  '获得=字符的位置
            nLen = Len(SignParas(i))                        '获得字符串长度
            itemName = Left(SignParas(i), pos - 1)          '获得变量名
            itemValue = Right(SignParas(i), nLen - pos)     '获得变量的值

            sHtml = sHtml.Append("<input type='hidden' name='" & itemName & "' value='" & itemValue & "'/>")
        Next

        sHtml = sHtml.Append("<input type='hidden' name='sign' value='" & sign & "'/>")
        sHtml = sHtml.Append("<input type='hidden' name='sign_type' value='" & sign_type & "'/>")

        'submit按钮控件请不要含有name属性
        sHtml = sHtml.Append("<input type=""submit"" value=""支付宝确认付款""></form>")

        If Not debug Then sHtml = sHtml.Append("<script>document.forms['alipaysubmit'].submit();</script>")

        Return sHtml.ToString()
    End Function

    ''' <summary>
    ''' 验证是否是支付宝服务器发来的请求
    ''' </summary>
    ''' <param name="notify_id">验证通知ID</param>
    ''' <returns>验证结果</returns>
    ''' <remarks></remarks>
    Public Function Verify(ByVal notify_id As String) As String

        Dim veryfy_url As String = ""

        If transport = "https" Then
            veryfy_url = gateway & "service=notify_verify&partner=" & partner & "&notify_id=" & notify_id
        Else
            veryfy_url = gateway + "partner=" + partner + "&notify_id=" + notify_id
        End If

        Return Get_Http(veryfy_url, 120000)

    End Function

    ''' <summary>
    ''' 获取远程服务器ATN结果
    ''' </summary>
    ''' <param name="a_strUrl">指定URL路径地址</param>
    ''' <param name="timeout">超时时间设置</param>
    ''' <returns>服务器ATN结果字符串</returns>
    ''' <remarks></remarks>
    Function Get_Http(ByVal a_strUrl As String, ByVal timeout As Integer) As String
        Dim strResult As String = ""
        Try
            Dim myReq As Net.HttpWebRequest = Nothing
            myReq = Net.HttpWebRequest.Create(a_strUrl)
            myReq.Timeout = timeout

            Dim HttpWResp As Net.HttpWebResponse = myReq.GetResponse
            Dim myStream As IO.Stream = HttpWResp.GetResponseStream
            Dim sr As New IO.StreamReader(myStream, Text.Encoding.Default)
            Dim strBuilder As New Text.StringBuilder

            Do While (sr.Peek() <> -1)
                strBuilder.Append(sr.ReadLine())
            Loop
            strResult = strBuilder.ToString()
        Catch ex As Exception

        End Try

        Return strResult
    End Function
End Class

' "_input_charset=" & input_charset, 
' "anti_phishing_key=" & anti_phishing_key, "exter_invoke_ip=" & exter_invoke_ip,
' "extra_common_param=" & extra_common_param, "buyer_email=" & buyer_email, "royalty_type=" & royalty_type, '
'"royalty_parameters=" & royalty_parameters}


<Serializable()> Public Class ParamItem
    ''' <summary>
    ''' 参数名称
    ''' </summary>
    ''' <remarks></remarks>
    <XmlAttribute()> Public name As String

    <XmlText()> Public value As String
End Class







